姓名 / 氏名
陳黃英
學號 / 学籍番号
1111310033
班級 / クラス
資訊科技應用系
日四技資料應四甲
Week 6 · 課程作業 · 工業物聯網

雙視訊人流計算
與趨勢分析系統

基於 YOLOv8 + EuclideanDistTracker 同時分析雙來源影像,即時呈現人數、峰值、趨勢與折線比較圖

YOLOv8n · Ultralytics OpenCV · VideoCapture Pillow · 中文繪圖 EuclideanDistTracker Python 3.12 · .venv

01 · 雙視訊人流分析系統介紹

系統概要與應用情境

🎯 系統目的

本系統同時讀取兩個影像來源(示範影片 + WebCam),透過 YOLOv8 偵測人物、EuclideanDistTracker 追蹤 ID,計算即時人數、累積 ID、峰值、短期平均、長期平均與趨勢,適用於抗議現場、集會活動雙來源比對分析。

📡 預設來源設定

群眾來源 Avideos/protest_demo.mp4
若影片不存在自動切換至 WebCam 0

群眾來源 B:本地 WebCam 0
若攝影機占用則自動切換至影片來源

🖥️ 畫面佈局

上方左右各顯示群眾 A、B,各自附資訊面板顯示人數、ID、峰值、平均值與狀態,下方為雙折線圖即時比較兩路人流變化趨勢。

⚙️ 核心技術

YOLOv8n — 人物偵測 conf=0.30
EuclideanDistTracker — threshold 45px
Pillow (PIL) — 中文文字繪製
deque(maxlen=120) — 滑動視窗

2
影像來源數
120
歷史幀緩衝
0.30
YOLO 信心值
45px
追蹤距離閾值
640×360
影像解析度

02 · 資訊專案結構

檔案架構說明

📁 20260401_1/
📁config/
⚙️crowd_config.json系統設定
📁videos/
🎬protest_demo.mp4示範影片
📄README.txt說明
📁docs/
📄01_system_summary.md
📄02_install_run_and_metrics.md
📄03_program_flow.md
📄04_troubleshooting.md
🐍app.py主程式
🐍tracker.py追蹤器
🤖yolov8n.ptYOLO 模型
📄README.md

app.py — 主程式

讀取 config → 建立兩個 CrowdMonitor → 載入 YOLO → 主迴圈同步處理雙路影像 → 拼合畫面並顯示。包含 CrowdStats、CrowdMonitor dataclass、自動備援切換、中文繪圖函式、折線圖生成。

tracker.py — 追蹤器

EuclideanDistTracker 使用質心歐氏距離匹配上一幀的物件 ID,threshold=45px,超出範圍視為新物件分配新 ID,同幀結束後清除非活躍 ID。

crowd_config.json — 系統設定

定義模型路徑、解析度、信心值、history_size,以及兩個來源的名稱、主要來源、備援清單與顯示顏色(accent)。


03 · 資訊系統環境圖 (UML)

系統架構圖與資料流

圖一:整體資料流(從影像輸入到畫面輸出)

INPUT A
protest_demo.mp4
VideoCapture
RESIZE
OpenCV
640×360
DETECT
YOLOv8n
conf=0.30
TRACK
EuclidDist
threshold=45
ANALYZE
CrowdStats
avg/peak/trend
RENDER
Dashboard
cv2.imshow

圖二:雙來源並行架構

來源 A
protest_demo.mp4
Monitor A
CrowdMonitor
YOLO+Track
process_frame()
Frame A
annotate+panel
來源 B
WebCam 0
Monitor B
CrowdMonitor
YOLO+Track
process_frame()
Frame B
annotate+panel
MERGE
hstack(A,B)
CHART
build_chart()
OUTPUT
cv2.imshow()

04 · 程式邏輯與安裝套件說明

程式流程與安裝步驟

安裝步驟

  • 切換到工作目錄
    cd C:\AI_Traffic_System‚60401_1

  • 安裝所需套件
    pip install -r .. equirements.txt

  • 將群眾影片放入
    20260401_1 ideos\protest_demo.mp4

  • 執行主程式
    python app.py

  • qEsc 結束程式

主要套件

ultralytics

YOLOv8 模型推論,輸出 bounding box xyxy 座標

opencv-python

VideoCapture 讀取影像、resize、imshow、polylines

Pillow (PIL)

ImageFont + ImageDraw 繪製中文文字至影像上

numpy

np.full 建立背景陣列、np.hstack/vstack 拼合畫面

程式流程說明

tracker.py — EuclideanDistTracker.update()
def update(self, objects_rect):
    objects_bbs_ids = []
    for rect in objects_rect:
        x, y, w, h = rect
        cx = (x + x + w) // 2   # 計算質心
        cy = (y + y + h) // 2

        same_object_detected = False
        for object_id, point in self.center_points.items():
            distance = math.hypot(cx - point[0], cy - point[1])
            if distance < self.distance_threshold:
                self.center_points[object_id] = (cx, cy)
                objects_bbs_ids.append([x, y, w, h, object_id])
                same_object_detected = True
                break
        if not same_object_detected:
            self.center_points[self.id_count] = (cx, cy)
            objects_bbs_ids.append([x, y, w, h, self.id_count])
            self.id_count += 1
    return objects_bbs_ids
app.py — classify_trend() 趨勢判斷邏輯
def classify_trend(history):
    if len(history) < 12:
        return "資料累積中"
    recent   = history[-6:]
    previous = history[-12:-6]
    delta    = mean(recent) - mean(previous)
    if   delta >=  6: return "快速上升"
    elif delta >=  2: return "緩步上升"
    elif delta <= -6: return "快速下降"
    elif delta <= -2: return "緩步下降"
    else:            return "大致穩定"

05 · 全系統功能

核心技術與功能說明

🧠

YOLOv8 人物偵測

使用 yolov8n.pt 輕量模型,只偵測 class 0(人物),confidence ≥ 0.30,輸出 bounding box (x1,y1,x2,y2)。

🔢

質心距離 ID 追蹤

EuclideanDistTracker 計算每幀質心與上幀的歐氏距離,<45px 沿用舊 ID,同一人只計算一次。

📊

趨勢判斷

比較最近 6 幀與前 6 幀平均差值 δ,分為快速上升 / 緩步上升 / 大致穩定 / 緩步下降 / 快速下降。

📈

雙折線圖比較

build_chart() 同時繪製兩路即時人數折線與 10 幀移動平均線,視覺化比較雙來源人流變化。

🔄

自動備援切換

reopen_next_source() 在主要來源失敗時依序嘗試 fallback_sources,確保系統不因來源中斷而停止。

🀄

Pillow 中文繪圖

使用 msjh.ttc / msyh.ttc 字型,透過 PIL ImageDraw 將中文資訊直接繪製到 NumPy 影像陣列上。

指標名稱說明計算方式
目前人數當幀追蹤到的活躍 ID 數量len(tracked)
累積辨識 ID曾出現過的唯一人物總數len(seen_ids)
峰值人數歷史最高單幀人數max(peak, current)
短期平均最近 10 幀的平均人數mean(history[-10:])
長期平均最近 30 幀的平均人數mean(history[-30:])
趨勢判讀6 幀差值 δ 分 5 級判斷classify_trend()
05-B · 實作過程記錄

實作過程截圖

以下為本次實作過程中的畫面截圖紀錄。


06 · 使用 AI 工具對話連結

AI 輔助開發記錄

🤖

Claude (claude.ai) — 系統設計與程式生成

輸入需求:「建立雙視訊人流分析系統,使用 YOLOv8 + EuclideanDistTracker,同時處理兩路影像並顯示趨勢折線圖」

使用AI工具對話連結
https://claude.ai/chat/4e1d734d-3c9b-46e6-8d07-2b13a1555067

Gemini — 除錯與套件問題諮詢

諮詢 Pillow 中文字型路徑設定、cv2.VideoCapture 備援切換邏輯、YOLOv8 classes 參數過濾人物偵測。

使用AI工具對話連結
https://gemini.google.com/share/4aae79465c79

07 · Trouble Shooting

問題排除紀錄

#問題描述原因分析解決方法狀態
01protest_demo.mp4 無法開啟影片未放入 videos/ 資料夾確認路徑,系統自動切換備援來源(WebCam 0)已解決
02中文文字顯示亂碼OpenCV putText 不支援中文改用 Pillow ImageFont + ImageDraw 繪製中文字已解決
03雙來源其中一路無畫面WebCam 被其他軟體占用關閉占用攝影機的程式後重啟,或調整 source 編號已解決
04人數數值波動過大YOLOv8 confidence 設定太低將 confidence 從 0.25 調高至 0.30,搭配折線圖平均線觀察已解決
05同一人被分配多個 IDdistance_threshold 太小將 EuclideanDistTracker threshold 從 30 調整為 45px已解決
06趨勢一直顯示「資料累積中」history 未達 12 幀門檻等待約 12 幀後自動更新;可降低門檻至 8 加速初始化觀察中

08 · 學習心得

學習心得與總結

本週最大的收穫是理解了「多來源並行處理」的架構設計思維。以往只處理單一影像,這次需要同時維護兩個 CrowdMonitor 的狀態、各自的歷史 deque、追蹤器與統計資料,讓我深刻體會到 dataclass 在管理複雜狀態時的優雅性。

EuclideanDistTracker 的設計非常直觀——質心距離 < 45px 就視為同一人。雖然簡單,但在固定場景下效果出乎意料地穩定。相比 Deep SORT 等複雜方法,它的計算量極低,非常適合 IoT 邊緣裝置部署。

自動備援切換(reopen_next_source)是這次系統最實用的工程設計。影片播完、攝影機斷線都能無縫切換,這種「防禦性設計」思維在工業 IoT 場景中非常重要。

使用 AI 工具(Claude)輔助生成程式骨架後,我花最多時間在「理解與調整」:為什麼 threshold 設 45 而不是 30?為什麼 short_avg 取 10 幀?這些數字背後的邏輯才是真正的學習。AI 給了答案,但理解答案的過程才讓知識真正內化。